#include <OgreVector3.h>
#include <OgreSceneManager.h>
#include <OgreCamera.h>
#include <OgreEntity.h>
#include <OgreLogManager.h>
#include <OgreRoot.h>
#include <OgreViewport.h>
#include <OgreRenderWindow.h>
#include <OgreConfigFile.h>
#include <math.h>

/* PHYSICS CONSTANTS */
#define NOISE 5			// simulates imperfection on materials by randomizing collision bounces to a certaion extent (5 for 5% bounce directional variation)

/* WORLD CONSTANTS */
#define WORLD_EDGE_LEFT -200
#define WORLD_EDGE_RIGHT 200
#define FLOOR -200
#define TOP 160

enum Material {IRON, MARBLE, WOOD, RUBBER};

// kollision: spiegle an lot des vektors welcher Kugelmittelpunkte verbindet
#pragma once

class Sphere
{
public:
	Sphere(Ogre::SceneManager *sceneManager, Ogre::String name, Material mat, Ogre::String texture, Ogre::Vector3 initPosition,  Ogre::Vector3 initAccel, Ogre::Vector3 size, Ogre::Real radius, bool collides);
	virtual ~Sphere(void);

	void move(const Ogre::FrameEvent& evt);
	void collisionCheck(void);
	void collideWith(Sphere *collider,const Ogre::FrameEvent& evt);

	// getters
	Ogre::Vector3 getPosition(void){return m_node->getPosition();}
	Ogre::Real getRadius(void){return m_radius;}
	Ogre::Vector3 getDispVector(void){return m_displacementVector;}
	Ogre::Real getGravity(void){return m_gravity;}
	Ogre::Real getBounce(void){return m_bounce;}
	Ogre::Real getFriction(void){return m_friction;}
	Ogre::Vector3 getPreviousPosition(void){return m_previousPosition;}
	bool isSelected(void){return m_selected;}
	bool getCollides(void){return m_collides;}
	Ogre::Vector3 getInitialPosition(){return m_initPosition;}

	//setters
	void setPosition(Ogre::Vector3 newPosition){m_node->setPosition(newPosition);}
	void setBoundingBox(bool setBox){m_node->showBoundingBox(setBox);}
	void setAcceleration(Ogre::Vector3 newAcceleation){m_displacementVector = newAcceleation;}
	void setGravity(Ogre::Real newGravity){m_gravity = newGravity;}
	void setBounce(Ogre::Real newBounce){m_bounce = newBounce;}
	void setFriction(Ogre::Real newFriction){m_friction = newFriction;}
	void setFreeze(bool freeze){m_freeze = freeze;}
	void setSelected(bool selected){m_selected = selected;}
	void setPreviousPosition(Ogre::Vector3 previousPosition){m_previousPosition = previousPosition;}
	void setCollides(bool collides){m_collides = true;}
	void setMousePosition(Ogre::Vector3 mousePosition){m_mousePosition = mousePosition;};
	void setInitialPosition(Ogre::Vector3 newInitial){m_initPosition = newInitial;};

protected:
	Ogre::SceneManager *m_scene;
    Ogre::SceneNode *m_node;

private:
	bool m_collides;
	bool m_freeze;
	bool m_selected;
	Ogre::Vector3 m_initPosition;
	Material m_mat;
	Ogre::Real m_radius;
	Ogre::Vector3 m_displacementVector;
	Ogre::Vector3 m_previousPosition;
	Ogre::Vector3 m_mousePosition;

	Ogre::Real m_gravity;
	Ogre::Real m_bounce;
	Ogre::Real m_friction;
};

